package auth

import (
	"bytes"
	"crypto/sha256"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"os"
	"time"

	"gitee.com/hexug/go-tools/logger"
)

// HTTP客户端配置
type HttpClient struct {
	Token   string
	BaseURL string
	Client  *http.Client
}

// 创建新的HTTP客户端实例
func NewHttpClient(token, baseURL string) *HttpClient {
	return &HttpClient{
		Token:   token,
		BaseURL: baseURL,
		Client: &http.Client{
			Timeout: 30 * time.Second, // 设置超时时间
			// 跳过证书验证
			Transport: &http.Transport{
				TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
			},
		},
	}
}

// 生成签名
func (c *HttpClient) generateSignature() (string, string) {
	timestamp := fmt.Sprintf("%d", time.Now().Unix())
	signStr := fmt.Sprintf("%s%s%s", timestamp, c.Token, timestamp)
	signature := fmt.Sprintf("%x", sha256.Sum256([]byte(signStr)))
	return timestamp, signature
}

// 发送HTTP请求的通用方法
func (c *HttpClient) DoRequest(method, path string, body interface{}) ([]byte, error) {
	// 构建完整URL
	url := c.BaseURL + path

	// 创建请求体
	var reqBody []byte
	var err error
	if body != nil {
		reqBody, err = json.Marshal(body)
		if err != nil {
			logger.L().Errorf("序列化请求体失败: %v", err)
			return nil, fmt.Errorf("序列化请求体失败: %v", err)
		}
	}

	// 创建请求，使用bytes.NewBuffer包装请求体
	req, err := http.NewRequest(method, url, bytes.NewBuffer(reqBody))
	if err != nil {
		logger.L().Failf("创建请求失败: %v", err)
		return nil, fmt.Errorf("创建请求失败: %v", err)
	}

	// 生成并设置签名信息
	timestamp, signature := c.generateSignature()
	req.Header.Set("Content-Type", "application/json;charset=UTF-8")
	req.Header.Set("timestamp", timestamp)
	req.Header.Set("signature", signature)

	// 发送请求
	resp, err := c.Client.Do(req)
	if err != nil {
		logger.L().Failf("发送请求失败: %v", err)
		return nil, fmt.Errorf("发送请求失败: %v", err)
	}
	defer resp.Body.Close()

	// 读取响应
	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		logger.L().Errorf("读取响应失败: %v", err)
		return nil, fmt.Errorf("读取响应失败: %v", err)
	}

	// 检查响应状态码
	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		logger.L().Failf("请求失败，状态码: %d，响应内容: %s", resp.StatusCode, string(respBody))
		return respBody, fmt.Errorf("请求失败，状态码: %d，响应内容: %s", resp.StatusCode, string(respBody))
	}

	return respBody, nil
}

// 发送 multipart/form-data POST 请求
func (c *HttpClient) PostMultipart(path string, files []string, fields map[string]string) ([]byte, error) {
	url := c.BaseURL + path

	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)

	// 多文件上传：都用 "files" 这个字段
	for _, filePath := range files {
		file, err := os.Open(filePath)
		if err != nil {
			logger.L().Errorf("打开文件失败 %s: %v", filePath, err)
			return nil, fmt.Errorf("打开文件失败 %s: %v", filePath, err)
		}
		defer file.Close()

		part, err := writer.CreateFormFile("files", filePath)
		if err != nil {
			logger.L().Errorf("创建文件字段失败: %v", err)
			return nil, fmt.Errorf("创建文件字段失败: %v", err)
		}
		_, err = io.Copy(part, file)
		if err != nil {
			logger.L().Errorf("写入文件失败: %v", err)
			return nil, fmt.Errorf("写入文件失败: %v", err)
		}
	}

	// 普通字段
	for key, value := range fields {
		if err := writer.WriteField(key, value); err != nil {
			logger.L().Errorf("写入字段失败: %v", err)
			return nil, fmt.Errorf("写入字段失败: %v", err)
		}
	}

	if err := writer.Close(); err != nil {
		logger.L().Errorf("关闭 writer 失败: %v", err)
		return nil, fmt.Errorf("关闭 writer 失败: %v", err)
	}

	// 构建请求
	req, err := http.NewRequest("POST", url, body)
	if err != nil {
		logger.L().Errorf("创建请求失败: %v", err)
		return nil, fmt.Errorf("创建请求失败: %v", err)
	}

	// 加签
	timestamp, signature := c.generateSignature()

	req.Header.Set("Content-Type", writer.FormDataContentType())
	req.Header.Set("timestamp", timestamp)
	req.Header.Set("signature", signature)

	resp, err := c.Client.Do(req)
	if err != nil {
		logger.L().Failf("发送请求失败: %v", err)
		return nil, fmt.Errorf("发送请求失败: %v", err)
	}
	defer resp.Body.Close()

	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		logger.L().Errorf("读取响应失败: %v", err)
		return nil, fmt.Errorf("读取响应失败: %v", err)
	}

	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		logger.L().Failf("请求失败，状态码: %d，响应内容: %s", resp.StatusCode, string(respBody))
		return respBody, fmt.Errorf("请求失败，状态码: %d，响应内容: %s", resp.StatusCode, string(respBody))
	}

	return respBody, nil
}

// 便捷方法：GET请求
func (c *HttpClient) Get(path string) ([]byte, error) {
	return c.DoRequest("GET", path, nil)
}

// 便捷方法：POST请求
func (c *HttpClient) Post(path string, body interface{}) ([]byte, error) {
	return c.DoRequest("POST", path, body)
}
